#! /usr/bin/perl -w

use strict;
use Getopt::Long;

my %hash;   # hast table, 数据结构见__DATA__段
my %opt;    # 命令行选项

GetOptions (
    "help|h"    => sub{   help()   },
    "debug|d"   => \$opt{ "debug"  },
    "strict|s"  => \$opt{ "strict" },
) or die "run [$0 --help] for help\n";

while (<>) {
    next unless /^BEGIN.*(ACCEPTCLIENT|CLOSE|RECVFROMSHM)/;
    chomp;
    my ( $time, $key, $flag ) = (split /\$/ )[1,2,3];
    &do_record ( $time, $key, $flag );
}

&debug                if $opt{ "debug"  };
&check_data_integrity if $opt{ "strict" };

my $g_key_cnt      = 0;       # 总 key 数
my $g_conect_cnt   = 0;       # 总连接次数
my $g_lasting_time = 0;       # 总持续时间
my $g_respon_time  = 0;       # 总响应时间

foreach my $k ( sort keys %hash ) {
    
    my $conect_total = 0;  # 该key总连接时间
    my $conect_cnt   = 0;  # 该key总连接次数
    my $respon_total = 0;  # 该key总响应时间


    print "=" x 78, "\n";
    print "连接信息(key)=$k\n";
    print "-" x 39, "\n";

    foreach my $st ( sort keys %{ $hash{ $k } } ) {

        my $accept  = 0;   # 起始时间点 ACCEPTCLIENT
        my $recv    = 0;   # 接收时间点 RECVFROMSHM
        my $close   = 0;   # 结束时间点 CLOSE
        my $respon  = 0;   # 响应时间
        my $lasting = 0;   # 持续时间

        next if $st eq "LAST_ACCEPT";

        $accept  = $hash{ $k }->{ $st }->{ ACCEPTCLIENT };
        $recv    = $hash{ $k }->{ $st }->{ RECVFROMSHM  };
        $close   = $hash{ $k }->{ $st }->{ CLOSE        };

        $respon  = $recv   - $accept;
        $lasting = $close  - $accept;

        print "时间跨度 = " . "$accept - $close"   . "\n";
        print "响应时间 = $respon\n";
        print "持续时间 = $lasting\n";
        print "\n";

        $conect_total += $lasting;
        $respon_total += $respon;
        $conect_cnt++;

        $g_conect_cnt++;
        $g_lasting_time += $lasting; 
        $g_respon_time += $respon;
    }

    print "-" x 39, "\n";
    next unless $conect_cnt;

    print "总共连接 $conect_cnt 次",
          " ,平均响应时间" . ( $respon_total / $conect_cnt ), 
          " ,该key总持续时间 $conect_total",
          " ,平均单次连接持续时间" . ($conect_total / $conect_cnt) . "\n";

    $g_key_cnt++;

}

print "=" x 78, "\n";
print "\n\n";
print "总共存在 $g_key_cnt 个可重复利用的key, 总共连接次数 $g_conect_cnt, ", 
      "全部连接持续时间和 $g_lasting_time\n" ,
      "平均响应时间 " . ( $g_respon_time / $g_conect_cnt ) . "\n";

# 将ACCEPTCLIENT RECVFROMSHM CLOSE记录在hash table中
sub do_record()
{
    my( $t, $k, $f ) = @_;
    my $last;

    # 生成一条新记录
    if ( $f eq "ACCEPTCLIENT" ) {
        $hash{ $k }->{ "LAST_ACCEPT" }          = $t;
        $hash{ $k }->{ $t }->{ "ACCEPTCLIENT" } = $t;
    }
    # 记录到最新的记录
    elsif ( $f eq "CLOSE" ) {
        return unless &check_start_for( $k );
        $last = &get_lasttime_for( $k );
        $hash{ $k }->{ $last }->{ "CLOSE" } = $t;
    }
    # 记录到最新的记录
    elsif ( $f eq "RECVFROMSHM" ) {
        return unless &check_start_for( $k );
        $last = &get_lasttime_for( $k );
        $hash{ $k }->{ $last }->{ "RECVFROMSHM" } = $t;
    }
}

# 检查是否已经有 ACCEPTCLIENT, 如果没有，则放弃这条记录
sub check_start_for()
{
    my $k = shift;

    if ( defined $hash{ $k }->{ "LAST_ACCEPT" } ) {
        return 1;
    }
    else {
        return 0;
    }
}

sub get_lasttime_for()
{
    my $k = shift;
    return $hash{ $k }->{ "LAST_ACCEPT" };
}

## 检查数据完整性, 删除不完整的key
sub check_data_integrity()
{
    foreach my $k ( sort keys %hash ) {
        foreach my $st ( sort keys %{ $hash{ $k } } ) {
            next if $st eq "LAST_ACCEPT";

            eval {
                defined $hash{ $k }->{ $st }->{ ACCEPTCLIENT } or 
                    die "ACCEPTCLIENT null in [$k -> $st]\n";
                defined $hash{ $k }->{ $st }->{ RECVFROMSHM  } or
                    die "RECVFROMSHM null in [$k -> $st]\n";
                defined $hash{ $k }->{ $st }->{ CLOSE        } or 
                    die "CLOSE null in [$k -> $st]\n";
            };
            warn "WARNING: $@" if $@;

            # delete the key whose data not integrit
            delete $hash{ $k }->{ $st } if $@;
        }
   }
}

## 调试， 打印数据结构
sub debug()
{
    use Data::Dumper;
    $Data::Dumper::Indent = 2;  # set to 1 for for compact format
    print Dumper (\%hash);
    exit 0;
}

sub help()
{
    print <<EOF;
    Usage: $0 [ --debug | --strict | --help ]
           $0 [ -d | -s | -h ]
EOF
    exit 0;
}


__DATA__
hash table 数据结构
'172.1.1.1:172.1.1.2:47573:81' => {
      '20090421092929.715189' => {
          'RECVFROMSHM' => '20090421092929.725509',
          'ACCEPTCLIENT' => '20090421092929.715189',
          'CLOSE' => '20090421092929.725592'
      },

      'LAST_ACCEPT' => '20090421092929.715189'
}
